package rpc.registry;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import rpc.protocol.InvokerProtocol;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;


public class RegistryHandler extends ChannelInboundHandlerAdapter {
    //保存所有可用的服务
    // key: 对外提供服务接口的完整路径-- java.rpc.IRpcHelloService
    public static ConcurrentHashMap<String,Object> registyMap = new ConcurrentHashMap<>();
    // 保存所有相关的服务类
    private List<String> classNames = new ArrayList<>();

    public RegistryHandler(){
        // 完成扫描
        scannerClass("rpc.provider");
        doRegister();
    }

    /**
     * 反射调用方法并写回调用结果
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Object result = new Object();
        InvokerProtocol request = (InvokerProtocol)msg;
        //rpc.api.IRpcHelloService
        if(registyMap.containsKey(request.getClassName())){
            Object clazz = registyMap.get(request.getClassName());
            //通过方法和形参获取到那个方法
            Method method = clazz.getClass().getMethod(request.getMethodName(),request.getParams());
            //通过反射调用方法
            result = method.invoke(clazz,request.getValues());
        }
        ctx.write(result);
        ctx.flush();
        ctx.close();
    }

    public void scannerClass(String packageName){
        URL url = this.getClass().getClassLoader().getResource(packageName.replaceAll("\\.","/"));
        File dir = new File(url.getFile());

        for(File file : dir.listFiles()){  //File[]
            if(file.isDirectory()){
                scannerClass(packageName+"."+file.getName());
            }else{
                classNames.add(packageName+"."+file.getName().replace(".class","").trim());
            }
        }
    }

    /**
     * 反射实力化实现类
     */
    public void doRegister(){
        if(classNames.size() == 0){
            return;
        }

        for(String className : classNames){
            try{
                //获得className的Class对象
                Class<?> clazz = Class.forName(className);
                // 实现的接口
                Class<?> i = clazz.getInterfaces()[0];
                // i.getName = rpc.IRpcHelloService
                registyMap.put(i.getName(),clazz.newInstance());
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
}
